package com.lonewalker.sparrow.config;

import com.alibaba.ttl.threadpool.TtlExecutors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 异步线程线程池配置类
 *
 * <p>使用方法：</p>
 * <pre>
 * 1.先注入线程池的bean
 * {@code @Resource}
 * private AsyncExecutorConfig asyncExecutorConfig;
 *
 * 2.具体的方法中异步调用
 * CompletableFuture.runAsync(() -> doSomeThing(……), asyncExecutorConfig.getAsyncExecutor());
 * </pre>
 *
 * @author LoneWalker
 */
@EnableAsync
@Configuration
public class AsyncExecutorConfig implements AsyncConfigurer {
    /**
     * 当前CPU的核数
     */
    private static final int FIXED_THREAD_POOL_SIZE = Runtime.getRuntime().availableProcessors();

    @Bean(name = "asyncExecutor")
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        // 核心线程数
        taskExecutor.setCorePoolSize(FIXED_THREAD_POOL_SIZE);
        // 最大线程数
        taskExecutor.setMaxPoolSize(FIXED_THREAD_POOL_SIZE * 2);
        // 最大等待队列数
        taskExecutor.setQueueCapacity(500);
        // 除核心线程，其他线程保留时间
        taskExecutor.setKeepAliveSeconds(60);
        // 线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean
        taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置线程池中任务的等待时间，超过时间强制销毁。
        taskExecutor.setAwaitTerminationSeconds(60);
        // 线程名前缀
        taskExecutor.setThreadNamePrefix("Sparrow-AsyncPool--");
        // 队列满之后，且创建的线程数大于最大线程数之后，直接使用调用任务的线程执行,谁调用谁处理(拒绝策略，要求情况高的情况可以入库后定时任务执行)
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.initialize();
        return TtlExecutors.getTtlExecutor(taskExecutor);
    }
}
